using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace StarSkipGame
{
    /// <summary>
    /// 粒子类型枚举
    /// </summary>
    public enum ParticleType
    {
        Explosion,
        Trail,
        Spark,
        Star,
        Dust
    }

    /// <summary>
    /// 粒子类
    /// </summary>
    public class Particle
    {
        public float X { get; set; }
        public float Y { get; set; }
        public float VelocityX { get; set; }
        public float VelocityY { get; set; }
        public float Life { get; set; }
        public float MaxLife { get; set; }
        public float Size { get; set; }
        public Color Color { get; set; }
        public ParticleType Type { get; set; }
        public float Rotation { get; set; }
        public float RotationSpeed { get; set; }
        public bool IsActive { get; set; }

        public Particle()
        {
            IsActive = true;
        }

        public void Update(float deltaTime)
        {
            if (!IsActive) return;

            // 更新位置
            X += VelocityX * deltaTime;
            Y += VelocityY * deltaTime;

            // 更新生命值
            Life -= deltaTime;
            if (Life <= 0)
            {
                IsActive = false;
                return;
            }

            // 更新旋转
            Rotation += RotationSpeed * deltaTime;

            // 根据类型更新特殊行为
            switch (Type)
            {
                case ParticleType.Explosion:
                    // 爆炸粒子逐渐减速
                    VelocityX *= 0.98f;
                    VelocityY *= 0.98f;
                    Size *= 0.99f;
                    break;

                case ParticleType.Trail:
                    // 尾迹粒子逐渐消失
                    Size *= 0.95f;
                    break;

                case ParticleType.Spark:
                    // 火花粒子快速消失
                    Size *= 0.9f;
                    break;

                case ParticleType.Star:
                    // 星星粒子闪烁效果
                    Size = (float)(Size * (0.8 + 0.2 * Math.Sin(Life * 10)));
                    break;

                case ParticleType.Dust:
                    // 尘埃粒子缓慢移动
                    VelocityX *= 0.99f;
                    VelocityY *= 0.99f;
                    break;
            }
        }

        public void Draw(Graphics g)
        {
            if (!IsActive) return;

            // 计算透明度
            float alpha = Life / MaxLife;
            Color particleColor = Color.FromArgb((int)(255 * alpha), Color);

            using (SolidBrush brush = new SolidBrush(particleColor))
            {
                switch (Type)
                {
                    case ParticleType.Explosion:
                        DrawExplosionParticle(g, brush);
                        break;

                    case ParticleType.Trail:
                        DrawTrailParticle(g, brush);
                        break;

                    case ParticleType.Spark:
                        DrawSparkParticle(g, brush);
                        break;

                    case ParticleType.Star:
                        DrawStarParticle(g, brush);
                        break;

                    case ParticleType.Dust:
                        DrawDustParticle(g, brush);
                        break;
                }
            }
        }

        private void DrawExplosionParticle(Graphics g, SolidBrush brush)
        {
            g.FillEllipse(brush, X - Size / 2, Y - Size / 2, Size, Size);
        }

        private void DrawTrailParticle(Graphics g, SolidBrush brush)
        {
            g.FillEllipse(brush, X - Size / 2, Y - Size / 2, Size, Size);
        }

        private void DrawSparkParticle(Graphics g, SolidBrush brush)
        {
            // 绘制十字形火花
            float halfSize = Size / 2;
            g.FillRectangle(brush, X - halfSize, Y - 1, Size, 2);
            g.FillRectangle(brush, X - 1, Y - halfSize, 2, Size);
        }

        private void DrawStarParticle(Graphics g, SolidBrush brush)
        {
            // 绘制五角星
            PointF[] points = new PointF[10];
            float radius = Size / 2;
            
            for (int i = 0; i < 10; i++)
            {
                float angle = (float)(i * Math.PI / 5 + Rotation);
                float r = (i % 2 == 0) ? radius : radius * 0.5f;
                points[i] = new PointF(
                    X + (float)(r * Math.Cos(angle)),
                    Y + (float)(r * Math.Sin(angle))
                );
            }
            
            g.FillPolygon(brush, points);
        }

        private void DrawDustParticle(Graphics g, SolidBrush brush)
        {
            g.FillEllipse(brush, X - Size / 2, Y - Size / 2, Size, Size);
        }
    }

    /// <summary>
    /// 粒子系统类
    /// </summary>
    public class ParticleSystem
    {
        private List<Particle> particles;
        private List<Particle> inactiveParticles; // 对象池：未激活的粒子
        private Random random;
        private const int MAX_PARTICLES = 1000; // 最大粒子数量限制
        private const int POOL_SIZE = 500; // 对象池大小

        public ParticleSystem()
        {
            particles = new List<Particle>();
            inactiveParticles = new List<Particle>();
            random = new Random();
            
            // 预分配粒子对象池
            InitializeParticlePool();
        }
        
        /// <summary>
        /// 初始化粒子对象池
        /// </summary>
        private void InitializeParticlePool()
        {
            for (int i = 0; i < POOL_SIZE; i++)
            {
                inactiveParticles.Add(new Particle());
            }
        }
        
        /// <summary>
        /// 从对象池获取粒子
        /// </summary>
        private Particle GetParticleFromPool()
        {
            if (inactiveParticles.Count > 0)
            {
                var particle = inactiveParticles[inactiveParticles.Count - 1];
                inactiveParticles.RemoveAt(inactiveParticles.Count - 1);
                particle.IsActive = true;
                return particle;
            }
            
            // 如果池中没有可用粒子，创建新的（但限制总数）
            if (particles.Count + inactiveParticles.Count < MAX_PARTICLES)
            {
                return new Particle();
            }
            
            return null; // 达到最大限制
        }
        
        /// <summary>
        /// 将粒子返回到对象池
        /// </summary>
        private void ReturnParticleToPool(Particle particle)
        {
            if (particle == null) return;
            
            particle.IsActive = false;
            particle.Life = 0;
            particle.VelocityX = 0;
            particle.VelocityY = 0;
            particle.Size = 0;
            particle.Rotation = 0;
            particle.RotationSpeed = 0;
            
            // 限制池的大小，避免无限增长
            if (inactiveParticles.Count < POOL_SIZE)
            {
                inactiveParticles.Add(particle);
            }
        }

        /// <summary>
        /// 创建爆炸效果
        /// </summary>
        /// <param name="x">爆炸中心X坐标</param>
        /// <param name="y">爆炸中心Y坐标</param>
        /// <param name="intensity">爆炸强度</param>
        public void CreateExplosion(float x, float y, float intensity = 1.0f)
        {
            int particleCount = (int)(20 * intensity);
            
            for (int i = 0; i < particleCount; i++)
            {
                var particle = GetParticleFromPool();
                if (particle == null) break; // 达到最大限制
                
                particle.X = x;
                particle.Y = y;
                particle.VelocityX = (float)(random.NextDouble() - 0.5) * 200 * intensity;
                particle.VelocityY = (float)(random.NextDouble() - 0.5) * 200 * intensity;
                particle.Life = (float)(random.NextDouble() * 0.5 + 0.5) * 2.0f;
                particle.MaxLife = 2.0f;
                particle.Size = (float)(random.NextDouble() * 3 + 2) * intensity;
                particle.Color = GetExplosionColor();
                particle.Type = ParticleType.Explosion;
                particle.RotationSpeed = (float)(random.NextDouble() - 0.5) * 10;
                
                particles.Add(particle);
            }
        }

        /// <summary>
        /// 创建尾迹效果
        /// </summary>
        /// <param name="x">位置X坐标</param>
        /// <param name="y">位置Y坐标</param>
        /// <param name="velocityX">速度X分量</param>
        /// <param name="velocityY">速度Y分量</param>
        public void CreateTrail(float x, float y, float velocityX, float velocityY)
        {
            var particle = GetParticleFromPool();
            if (particle == null) return; // 达到最大限制
            
            particle.X = x;
            particle.Y = y;
            particle.VelocityX = -velocityX * 0.1f;
            particle.VelocityY = -velocityY * 0.1f;
            particle.Life = 0.5f;
            particle.MaxLife = 0.5f;
            particle.Size = 2;
            particle.Color = Color.Cyan;
            particle.Type = ParticleType.Trail;
            
            particles.Add(particle);
        }

        /// <summary>
        /// 创建火花效果
        /// </summary>
        /// <param name="x">位置X坐标</param>
        /// <param name="y">位置Y坐标</param>
        public void CreateSpark(float x, float y)
        {
            for (int i = 0; i < 5; i++)
            {
                var particle = GetParticleFromPool();
                if (particle == null) break; // 达到最大限制
                
                particle.X = x + (float)(random.NextDouble() - 0.5) * 10;
                particle.Y = y + (float)(random.NextDouble() - 0.5) * 10;
                particle.VelocityX = (float)(random.NextDouble() - 0.5) * 100;
                particle.VelocityY = (float)(random.NextDouble() - 0.5) * 100;
                particle.Life = (float)(random.NextDouble() * 0.3 + 0.2);
                particle.MaxLife = 0.5f;
                particle.Size = (float)(random.NextDouble() * 2 + 1);
                particle.Color = Color.Yellow;
                particle.Type = ParticleType.Spark;
                
                particles.Add(particle);
            }
        }

        /// <summary>
        /// 创建星星效果
        /// </summary>
        /// <param name="x">位置X坐标</param>
        /// <param name="y">位置Y坐标</param>
        public void CreateStar(float x, float y)
        {
            var particle = GetParticleFromPool();
            if (particle == null) return; // 达到最大限制
            
            particle.X = x;
            particle.Y = y;
            particle.VelocityX = (float)(random.NextDouble() - 0.5) * 50;
            particle.VelocityY = (float)(random.NextDouble() - 0.5) * 50;
            particle.Life = (float)(random.NextDouble() * 1 + 1);
            particle.MaxLife = 2.0f;
            particle.Size = (float)(random.NextDouble() * 3 + 2);
            particle.Color = Color.White;
            particle.Type = ParticleType.Star;
            particle.RotationSpeed = (float)(random.NextDouble() - 0.5) * 5;
            
            particles.Add(particle);
        }

        /// <summary>
        /// 创建尘埃效果
        /// </summary>
        /// <param name="x">位置X坐标</param>
        /// <param name="y">位置Y坐标</param>
        public void CreateDust(float x, float y)
        {
            var particle = GetParticleFromPool();
            if (particle == null) return; // 达到最大限制
            
            particle.X = x;
            particle.Y = y;
            particle.VelocityX = (float)(random.NextDouble() - 0.5) * 20;
            particle.VelocityY = (float)(random.NextDouble() - 0.5) * 20;
            particle.Life = (float)(random.NextDouble() * 2 + 1);
            particle.MaxLife = 3.0f;
            particle.Size = (float)(random.NextDouble() * 2 + 1);
            particle.Color = Color.Gray;
            particle.Type = ParticleType.Dust;
            particle.RotationSpeed = (float)(random.NextDouble() - 0.5) * 2;
            
            particles.Add(particle);
        }

        /// <summary>
        /// 更新所有粒子
        /// </summary>
        /// <param name="deltaTime">时间间隔</param>
        public void Update(float deltaTime)
        {
            // 从后往前遍历，以便安全移除
            for (int i = particles.Count - 1; i >= 0; i--)
            {
                var particle = particles[i];
                particle.Update(deltaTime);
                
                // 如果粒子死亡，将其返回到对象池并从活动列表中移除
                if (!particle.IsActive)
                {
                    ReturnParticleToPool(particle);
                    particles.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// 绘制所有粒子
        /// </summary>
        /// <param name="g">图形对象</param>
        public void Draw(Graphics g)
        {
            // 设置高质量渲染
            g.SmoothingMode = SmoothingMode.AntiAlias;
            
            foreach (var particle in particles)
            {
                particle.Draw(g);
            }
        }

        /// <summary>
        /// 清除所有粒子
        /// </summary>
        public void Clear()
        {
            // 将所有活动粒子返回到对象池
            foreach (var particle in particles)
            {
                ReturnParticleToPool(particle);
            }
            
            particles.Clear();
        }

        /// <summary>
        /// 获取爆炸颜色
        /// </summary>
        /// <returns>随机爆炸颜色</returns>
        private Color GetExplosionColor()
        {
            Color[] colors = { Color.Orange, Color.Red, Color.Yellow, Color.OrangeRed };
            return colors[random.Next(colors.Length)];
        }

        /// <summary>
        /// 获取活跃粒子数量
        /// </summary>
        public int ActiveParticleCount
        {
            get { return particles.Count; }
        }
        
        /// <summary>
        /// 获取总粒子数量（活跃 + 池中）
        /// </summary>
        public int TotalParticleCount
        {
            get { return particles.Count + inactiveParticles.Count; }
        }
        
        /// <summary>
        /// 获取池中可用粒子数量
        /// </summary>
        public int PooledParticleCount
        {
            get { return inactiveParticles.Count; }
        }
    }
} 